package com.niiwoo.civet.account.service.local.trade;

import com.alibaba.fastjson.JSON;
import com.niiwoo.civet.account.dao.entity.TransFreezeOrder;
import com.niiwoo.civet.account.dao.entity.TransUnfreezeOrder;
import com.niiwoo.civet.account.dao.entity.TransUnfreezeOrderExample;
import com.niiwoo.civet.account.dao.mapper.TransFreezeOrderMapperExt;
import com.niiwoo.civet.account.dao.mapper.TransUnfreezeOrderMapperExt;
import com.niiwoo.civet.account.dto.common.MoneyTotalDTO;
import com.niiwoo.civet.account.enums.*;
import com.niiwoo.civet.account.service.local.MoneyTotalLocalService;
import com.niiwoo.civet.account.service.local.bill.BillFacade;
import com.niiwoo.civet.base.enums.CommonResultEnum;
import com.niiwoo.civet.trade.constant.MqConstant;
import com.niiwoo.civet.trade.dto.common.RefundUnfreezeResultMsgDTO;
import com.niiwoo.tripod.provider.exception.BizException;
import lombok.extern.slf4j.Slf4j;
import org.joda.time.DateTime;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * 交易解冻本地服务类
 * Created by wangjichao on 2018/4/23.
 */
@Service
@Slf4j
public class TransUnfreezeLocalService {
    @Autowired
    private TransUnfreezeOrderMapperExt transUnfreezeOrderMapperExt;

    @Autowired
    private TransFreezeOrderMapperExt transFreezeOrderMapperExt;

    @Autowired
    private BillFacade billFacade;

    @Autowired
    private RabbitTemplate rabbitTemplate;

    @Autowired
    private MoneyTotalLocalService moneyTotalLocalService;

    @Autowired
    private TransFreezeLocalService transFreezeLocalService;

    /**
     * 插入解冻订单
     * @param transUnfreezeOrder
     */
    public Integer insertTransUnfreezeOrder(TransUnfreezeOrder transUnfreezeOrder){
        return transUnfreezeOrderMapperExt.insertSelective(transUnfreezeOrder);
    }

    @Transactional
    public void transUnfreezeInitSynchronized(Long freezeId,TransUnfreezeOrder transUnfreezeOrder){
        //锁定冻结订单
        TransFreezeOrder transFreezeOrder = transFreezeOrderMapperExt.selectByPrimaryKeyForUpdate(freezeId);
        //冻结成功才可以解冻
        if(!TransFreezeStatusEnum.SUCCESS.getValue().equals(transFreezeOrder.getStatus())){
            throw new BizException("ACC31002");
        }
        //如果已全额解冻，幂等处理
        if(TransUnfreezeDegreeEnum.ALL_UNFREEZE.getValue().equals(transFreezeOrder.getUnfreezeDegree())){
            throw new BizException("ACC31004");
        }
        //有未明确状态的解冻请求
        List<TransUnfreezeOrder> transUnfreezeOrderList = this.listTransUnfreezeOrderInProcess();
        if(transUnfreezeOrderList!=null && transUnfreezeOrderList.size() > 0){
            throw new BizException("ACC31005");
        }
        this.insertTransUnfreezeOrder(transUnfreezeOrder);
    }

    /**
     * 查询所有状态为处理中的解冻订单
     * @return
     */
    public List<TransUnfreezeOrder> listTransUnfreezeOrderInProcess(){
        TransUnfreezeOrderExample example = new TransUnfreezeOrderExample();
        TransUnfreezeOrderExample.Criteria criteria = example.createCriteria();
        criteria.andStatusEqualTo(TransUnfreezeStatusEnum.HANDLING.getValue());//状态为处理中
        List<TransUnfreezeOrder> transUnfreezeOrders = transUnfreezeOrderMapperExt.selectByExample(example);
        return transUnfreezeOrders;
    }


    @Transactional
    public void unfreezeSuccess(Long freezeId,Long unfreezeId){
        Date now = new Date();
        BigDecimal unfreezeAmount = BigDecimal.ZERO;
        //锁定冻结记录
        TransFreezeOrder transFreezeOrder = transFreezeOrderMapperExt.selectByPrimaryKeyForUpdate(freezeId);
        //如果已全额解冻直接幂等返回
        if(TransUnfreezeDegreeEnum.ALL_UNFREEZE.getValue().equals(transFreezeOrder.getUnfreezeDegree())){
            return;
        }
        //锁定解冻记录
        TransUnfreezeOrder transUnfreezeOrder = transUnfreezeOrderMapperExt.selectByPrimaryKeyForUpdate(unfreezeId);
        //解冻记录非处理中直接返回幂等处理
        if(!TransUnfreezeStatusEnum.HANDLING.getValue().equals(transUnfreezeOrder.getStatus())){
            return;
        }

        //更新解冻记录为成功
        TransUnfreezeOrder updateUnfreezeOrder = new TransUnfreezeOrder();
        updateUnfreezeOrder.setId(unfreezeId);
        updateUnfreezeOrder.setStatus(TransUnfreezeStatusEnum.SUCCESS.getValue());
        updateUnfreezeOrder.setTransactionTime(now);
        updateUnfreezeOrder.setUpdateTime(now);
        transUnfreezeOrderMapperExt.updateByPrimaryKeySelective(updateUnfreezeOrder);

        //计算已解冻金额
        unfreezeAmount = transFreezeOrder.getUnfreezeAmount().add(transUnfreezeOrder.getAmount());
        //更新冻结订单解冻金额以及解冻状态
        TransFreezeOrder updateFreezeOrder = new TransFreezeOrder();
        updateFreezeOrder.setId(freezeId);
        updateFreezeOrder.setUnfreezeAmount(unfreezeAmount);
        updateFreezeOrder.setUnfreezeDegree(TransUnfreezeDegreeEnum.PART_UNFREEZE.getValue());//默认部分解冻
        updateFreezeOrder.setUpdateTime(now);
        //如果已全额解冻
        if(unfreezeAmount.compareTo(transFreezeOrder.getAmount()) == 0){
            updateFreezeOrder.setUnfreezeDegree(TransUnfreezeDegreeEnum.ALL_UNFREEZE.getValue());
        }
        transFreezeOrderMapperExt.updateByPrimaryKeySelective(updateFreezeOrder);
        //反向流水，关闭账单，变更余额
        billFacade.closeAndRevertBill(String.valueOf(transFreezeOrder.getOrderId()),OrderTypeEnum.enumOf(transFreezeOrder.getOrderType()),"");

        //维护moneytotal
        this.unfreezeSuccessMoneyTotalProcess(transUnfreezeOrder);

        //事务提交之后发送冻结成功消息
        sendTransUnfreezeResultMQMsg(transUnfreezeOrder,CommonResultEnum.SUCCESS);
    }


    @Transactional
    public void unfreezeFailure(Long unfreezeId,String errorCode,String errorMessage){
        Date now = new Date();
        //锁定解冻记录
        TransUnfreezeOrder transUnfreezeOrder = transUnfreezeOrderMapperExt.selectByPrimaryKeyForUpdate(unfreezeId);
        //解冻记录非处理中直接返回幂等处理
        if(!TransUnfreezeStatusEnum.HANDLING.getValue().equals(transUnfreezeOrder.getStatus())){
            return;
        }
        //更新解冻记录为成功
        TransUnfreezeOrder updateUnfreezeOrder = new TransUnfreezeOrder();
        updateUnfreezeOrder.setId(unfreezeId);
        updateUnfreezeOrder.setStatus(TransUnfreezeStatusEnum.FAIL.getValue());
        updateUnfreezeOrder.setErrorCode(errorCode);
        updateUnfreezeOrder.setErrorMessage(errorMessage);
        updateUnfreezeOrder.setUpdateTime(now);
        transUnfreezeOrderMapperExt.updateByPrimaryKeySelective(updateUnfreezeOrder);

        //事务提交之后发送冻结失败消息
        transUnfreezeOrder.setErrorCode(errorCode);
        transUnfreezeOrder.setErrorMessage(errorMessage);
        sendTransUnfreezeResultMQMsg(transUnfreezeOrder,CommonResultEnum.FAILURE);
    }

    /**
     * 订单解冻
     * @param transUnfreezeOrder
     */
    private void unfreezeSuccessMoneyTotalProcess(TransUnfreezeOrder transUnfreezeOrder){
        OrderTypeEnum orderTypeEnum = OrderTypeEnum.enumOf(transUnfreezeOrder.getOrderType());
        //仅还款时维护
        if(OrderTypeEnum.REPAYMENT.getCode().equals(transUnfreezeOrder.getOrderType())){
            List<MoneyTotalDTO> moneyTotalDTOs = new ArrayList<>();
            MoneyTotalDTO refund = new MoneyTotalDTO();
            refund.setAccountId(transUnfreezeOrder.getAccountId());
            refund.setUserId(transUnfreezeOrder.getUserId());
            refund.setAmount(transUnfreezeOrder.getAmount().negate());
            refund.setAmountType(AccountAmountTypeEnum.REPAYMENT_FREEZE);
            moneyTotalDTOs.add(refund);
            //统计金额更新
            moneyTotalLocalService.moneyTotal(moneyTotalDTOs);
        }
    }

    /**
     * 发送解冻结果
     * @param transUnfreezeOrder
     * @param commonResultEnum
     */
    private void sendTransUnfreezeResultMQMsg(TransUnfreezeOrder transUnfreezeOrder,CommonResultEnum commonResultEnum){
        //还款/垫付
        if(OrderTypeEnum.REPAYMENT.getCode().equals(transUnfreezeOrder.getOrderType())
                || OrderTypeEnum.GUARANTEE.getCode().equals(transUnfreezeOrder.getOrderType())){
            this.sendRefundUnFreezeResultMsg(transUnfreezeOrder,commonResultEnum);
        }
    }


    /**
     * 还款交易解冻
     * @param transUnfreezeOrder
     * @param commonResultEnum
     */
    private void sendRefundUnFreezeResultMsg(TransUnfreezeOrder transUnfreezeOrder,CommonResultEnum commonResultEnum){
        RefundUnfreezeResultMsgDTO refundUnFreezeResultMsgDTO = new RefundUnfreezeResultMsgDTO();
        refundUnFreezeResultMsgDTO.setOrderId(transUnfreezeOrder.getOrderId());
        refundUnFreezeResultMsgDTO.setAmount(transUnfreezeOrder.getAmount());
        refundUnFreezeResultMsgDTO.setUnfreezeRequestNo(transUnfreezeOrder.getRequestNo());
        refundUnFreezeResultMsgDTO.setFreezeResult(commonResultEnum);
        refundUnFreezeResultMsgDTO.setErrorCode(transUnfreezeOrder.getErrorCode());
        refundUnFreezeResultMsgDTO.setErrorMessage(transUnfreezeOrder.getErrorMessage());
        log.info("准备发送交易解冻结果MQ消息:{}", JSON.toJSONString(refundUnFreezeResultMsgDTO));
        rabbitTemplate.convertAndSend(MqConstant.REFUND_UNFREEZE_RESULT_EXCHANGE, MqConstant.REFUND_UNFREEZE_RESULT_ROUTING,refundUnFreezeResultMsgDTO);
    }

    /**
     * 解冻补单JOB查询数据
     * @return
     */
    public List<TransUnfreezeOrder> listOrdersForUnfreezeCheckJob(){
        TransUnfreezeOrderExample example = new TransUnfreezeOrderExample();
        TransUnfreezeOrderExample.Criteria criteria = example.createCriteria();
        criteria.andStatusEqualTo(TransUnfreezeStatusEnum.HANDLING.getValue());//状态为处理中
        criteria.andCreateTimeLessThan(new DateTime(new Date()).minusMinutes(5).toDate());//不包括最近5分钟创建的
        criteria.andUpdateTimeGreaterThan(new DateTime(new Date()).minusDays(2).toDate());//最多扫描范围两天
        List<TransUnfreezeOrder> transUnfreezeOrders = transUnfreezeOrderMapperExt.selectByExample(example);
        return transUnfreezeOrders;
    }


}
